vlwkaos' digital garden

TypeScript - Enums

Number Enums

기본적으로 TypeScript의 Enum은 숫자 기반이다.

enum Color {
  Red, // 0
  Green,
  Blue,
}

var col = Color.Red // 0

Enum은 다음의 JavaScript 코드의 Syntactic sugar이다.

예를 들어 다음의 TypeScript 코드는

enum Tristate {
  False,
  True,
  Unknown,
}

다음의 JavaScript코드를 생성한다.

var Tristate
;(function (Tristate) {
  Tristate[(Tristate["False"] = 0)] = "False"
  Tristate[(Tristate["True"] = 1)] = "True"
  Tristate[(Tristate["Unknown"] = 2)] = "Unknown"
})(Tristate || (Tristate = {}))

IIFE의 가장 첫번째 줄을 살펴보자

  • Tristate["False"] = 0{False: 0} 이된다. 그리고 이 과정에서 0이 반환되므로
  • Tristate[0] = "False" 가 수행된다.

즉, Tristate에 대해 숫자로 각 Enum의 이름들 (key)을 참조할 수 있고 이름(key)으로는 해당되는 숫자를 참조할 수 있다.

...
Tristate[0] // "False"
Tristate["False"] // 0

Number Enum에 직접 숫자를 부여하는 경우, 부여된 숫자부터 차례대로 상승한다.

enum Color {
  DarkRed = 3, // 3
  DarkGreen, // 4
  DarkBlue, // 5
}

이를 이용해서 첫번째 enum값은 1로 지정하는게 낫다. 왜냐하면 코드에서 enum값이 전달되는지 truthy 체크시에 0번째부터 시작하면 0 == false 로 실수할 가능성이 있기 때문이다.

Number Enum을 flag로 사용하기

enum AnimalFlags {
  None = 0,
  HasClaws = 1 << 0,
  CanFly = 1 << 1,
}
type Animal = {
  flags: AnimalFlags
}

function printAnimalAbilities(animal: Animal) {
  var animalFlags = animal.flags
  if (animalFlags & AnimalFlags.HasClaws) {
    console.log("animal has claws")
  }
  if (animalFlags & AnimalFlags.CanFly) {
    console.log("animal can fly")
  }
  if (animalFlags == AnimalFlags.None) {
    console.log("nothing")
  }
}

let animal: Animal = { flags: AnimalFlags.None }
printAnimalAbilities(animal) // nothing
animal.flags |= AnimalFlags.HasClaws
printAnimalAbilities(animal) // animal has claws
animal.flags &= ~AnimalFlags.HasClaws
printAnimalAbilities(animal) // nothing
animal.flags |= AnimalFlags.HasClaws | AnimalFlags.CanFly
printAnimalAbilities(animal) // animal has claws, animal can fly

각 자리수를 flag로 이용하면

  • &를 이용하여 해당 플래그가 활성화됐는지 확인 가능
  • |= 를 이용하여 flag 추가
  • &= ~AnimalFlags.HasClaws 로 취소

이렇게 사용할 수 있음.

그리고

enum AnimalFlags {
  None = 0,
  HasClaws = 1 << 0,
  CanFly = 1 << 1,
  EatsFish = 1 << 2,
  Endangered = 1 << 3,

  EndangeredFlyingClawedFishEating = HasClaws | CanFly | EatsFish | Endangered,
}

이런식으로 조합 flag도 만들 수 있다.

String Enums

값을 문자열로 지정할 수 있다. 장점은 문자열 비교 + 디버깅이 좀 더 수월함.

Const Enums

이건 지금도 지원하는지 모르겠지만.

const enum Tristate { // 앞에 const에 주목
    False,
    True,
    Unknown
}

var lie = Tristate.False;

이렇게하면 아까 처럼 함수로감싼 형태의 JavaScript코드가 만들어지는게 아니라 그냥 단순히 Enum에 해당하는 값을 바로 assign해버린다.

var lie = 0

Enum namespace merging

enum은 같은 이름을 가질 경우 합쳐서 추가됨. enum + enum, enum + namespace

TypeScript - Enums